package org.lgiavedoni.android.franq.core.dao;

import java.util.ArrayList;
import java.util.List;

import org.lgiavedoni.android.franq.core.sync.Synchronizable;
import org.lgiavedoni.android.franq.service.db.DbService;
import org.lgiavedoni.android.franq.service.log.Logger;
import org.lgiavedoni.android.franq.util.collection.CollectionUtils;

import com.db4o.query.Predicate;

public abstract class AbstractDAO<obj extends DaoObject> {

	// protected final List<DaoObject> objects = new ArrayList<DaoObject>();

	protected AbstractDAO() {
	}

	protected final DbService dbService = DbService.inst;

	public void add(obj o) {
		if (o == null) {
			Logger.inst.warning("Obj ingnored");
			return;
		}
		Logger.inst.debug("Adding: " + o);
		dbService.saveObject(o);
		checkSize();
	}

	public void add(List<obj> object) {
		if (object != null)
			for (obj o : object) {
				add(o);
			}
	}

	public int getMaxSize() {
		return 100;
	}

	public List<obj> getAll() {
		return (List<obj>) dbService.getAll(getObjectClass());
	}

	public List<?> getAllInstanceOf(Class c) {
		return dbService.getAll(c);
	}

	public List<obj> getAllByExample(obj exaObject) {
		return (List<obj>) dbService.queryByExample(exaObject);
	}

	protected List<obj> executeQueryPredicate(Predicate<obj> p) {
		return (List<obj>) dbService.query(p);
	}

	public void update(obj object) {
		dbService.updateObject(object);
	}

	public void update(List<obj> object) {
		if (object != null)
			for (obj o : object) {
				update(o);
			}
	}

	public abstract Class getObjectClass();

	public List<obj> getLast(int numOfObj) {
		return CollectionUtils.getLast(getAll(), numOfObj);
	}

	public obj getLast() {
		List l = getAll();
		return (obj) (l.size() > 0 ? l.get(l.size() - 1) : null);
	}

	public List<Synchronizable> getAllNoSyncronized() {
		List<Synchronizable> list = new ArrayList<Synchronizable>();
		for (DaoObject obj : getAll()) {
			if ((obj instanceof Synchronizable) && !((Synchronizable) obj).isSyncronized())
				list.add((Synchronizable) obj);
		}
		return list;
	}

	public long count() {
		return dbService.count(getObjectClass());
	}

	protected void checkSize() {
		// while (count() > getMaxSize())
		// dbService.delete(getAll().get(getAll().size() - 1));
	}

	public void deleteAll() {
		for (DaoObject obj : getAll()) {
			dbService.delete(obj);
		}
	}

	public void delete(List<obj> list) {
		for (DaoObject obj : list) {
			dbService.delete(obj);
		}
	}

	public void delete(obj o) {
		dbService.delete(o);
	}
}
